﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using NetAsmChecker.MainWpfUI.Properties;

namespace NetAsmChecker.MainWpfUI
{
	/// <summary>
	/// Interaction logic for AssembliesTypsWindow.xaml
	/// </summary>
	public partial class AssembliesTypsWindow : Window
	{
		public AssembliesTypsWindow()
		{
			InitializeComponent();
		}

		private ObservableCollection<AssemblyTypeViewModel> collectionAssemblies = new ObservableCollection<AssemblyTypeViewModel>();

		private void lsvAssemblies_Drop(object sender, DragEventArgs e)
		{
			object o = e.Data.GetData(DataFormats.FileDrop);
			if (o != null)
			{
				string[] files = o as string[];
				if (files != null && files.Length > 0)
				{
                    foreach (string file in files)
                    {
                        FileInfo fInfo = new FileInfo(file);
                        if (fInfo.Extension.Equals(".dll", StringComparison.InvariantCultureIgnoreCase)
                            || fInfo.Extension.Equals(".exe", StringComparison.InvariantCultureIgnoreCase))
                        {
                            try
                            {
                                Assembly asm = Assembly.LoadFrom(fInfo.FullName);
                                Module[] modules = asm.GetModules(false);
                                if (modules != null && modules.Count() > 0)
                                {
                                    PortableExecutableKinds peKinds;
                                    ImageFileMachine ifMachine;
                                    modules[0].GetPEKind(out peKinds, out ifMachine);

                                    this.collectionAssemblies.Add(new AssemblyTypeViewModel
                                    {
                                        AssemblyName = fInfo.Name,
                                        PortableExecutableKinds = peKinds,
                                        ImageFileMachine = ifMachine
                                    });
                                }
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                        }
                    }
				}
			}
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			this.lsvAssemblies.ItemsSource = this.collectionAssemblies;
		}
	}

	public class AssemblyTypeViewModel
	{
		private static Dictionary<PortableExecutableKinds, string> dicPEKinds = new Dictionary<PortableExecutableKinds, string>();
		private static Dictionary<ImageFileMachine, string> dicIFMachines = new Dictionary<ImageFileMachine, string>();

        static AssemblyTypeViewModel()
        {
            dicPEKinds.Add(PortableExecutableKinds.NotAPortableExecutableImage, Resources.NotAPortableExecutableImage);
            dicPEKinds.Add(PortableExecutableKinds.ILOnly, Resources.ILOnly);
            dicPEKinds.Add(PortableExecutableKinds.Required32Bit, Resources.Required32Bit);
            dicPEKinds.Add(PortableExecutableKinds.PE32Plus, Resources.PE32Plus);
            dicPEKinds.Add(PortableExecutableKinds.Unmanaged32Bit, Resources.Unmanaged32Bit);

            dicIFMachines.Add(ImageFileMachine.I386, Resources.I386);
            dicIFMachines.Add(ImageFileMachine.IA64, Resources.IA64);
            dicIFMachines.Add(ImageFileMachine.AMD64, Resources.AMD64);
        }
        
		private string assemblyName;

		public string AssemblyName
		{
			get { return assemblyName; }
			set { assemblyName = value; }
		}

		private PortableExecutableKinds peKinds;

		public PortableExecutableKinds PortableExecutableKinds
		{
			get { return peKinds; }
			set { peKinds = value; }
		}

		public string PortableExecutableKindsToolTip
		{
			get
			{
				StringBuilder sb = new StringBuilder();

				if (this.PortableExecutableKinds == System.Reflection.PortableExecutableKinds.NotAPortableExecutableImage)
				{
					sb.AppendLine(System.Reflection.PortableExecutableKinds.NotAPortableExecutableImage.ToString());
					sb.AppendLine(dicPEKinds[System.Reflection.PortableExecutableKinds.NotAPortableExecutableImage]);
				}
				else
				{
					foreach (PortableExecutableKinds peKind in dicPEKinds.Keys)
					{
						if ((peKind & this.PortableExecutableKinds) == peKind && peKind != System.Reflection.PortableExecutableKinds.NotAPortableExecutableImage)
						{
							if (sb.Length > 0)
							{
								sb.AppendLine();
							}
							sb.AppendLine(peKind.ToString());
							sb.AppendLine(dicPEKinds[peKind]);
						}
					}
				}

				return sb.ToString();
			}
		}

		private ImageFileMachine ifMachine;

		public ImageFileMachine ImageFileMachine
		{
			get { return ifMachine; }
			set { ifMachine = value; }
		}

		public string ImageFileMachineToolTip
		{
			get
			{
				StringBuilder sb = new StringBuilder();

				foreach (ImageFileMachine ifMachine in dicIFMachines.Keys)
				{
					if ((ifMachine | this.ImageFileMachine) == ifMachine)
					{
						if (sb.Length > 0)
						{
							sb.AppendLine();
						}
						sb.AppendLine(ifMachine.ToString());
						sb.AppendLine(dicIFMachines[ifMachine]);
					}
				}

				return sb.ToString();
			}
		}
	}
}
